﻿#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QDebug>
#include <QDesktopWidget>
#include <QProcess>
#include <QSystemTrayIcon>
#include <QLabel>
#include <QList>
#include <functional>

#include "Log/logger.h"
#include "devicemanager.h"
#include "waitutils.h"
#include "tablewidgetutils.h"
#include "widgetutils.h"
#include "fileutils.h"
#include "apputils.h"
#include "SpectroMeter/AvsSpectroMeterUtils.h"
#include "GlobalVar.h"
#include "DialogValid.h"
#include "quihelper.h"
#include "ConsumerWorker.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    qInstallMessageHandler(Logger::CustomMessageHandler);
    qDebug()<<__FUNCTION__<<__LINE__;
    connect(&Logger::Instance(),SIGNAL(OnLogging(QString)),this,SLOT(Log(QString)));
    _plotWrap=new SpectrumPlotWrap(ui->plot);
    _plotWrap->SetGraph(QStringList()<<"测量光谱"<<"处理后光谱");


    WidgetUtils::Execute(this,[this]()
    {
        qDebug()<<GlobalVar::Instance().Setting->allKeys();

        DeviceManager::Instance();
        DeviceManager::Instance().Init();

        SetSpectroControl(false);
        _spectroControl=&SpectroMeterControl::Instance();
        ui->tabWidget->setCurrentIndex(0);
        TableWidgetUtils::SetHeader(ui->tableWidgetSpectroInfo,SpectroInfoTag::GetHeaders());

        SetMeasureParam(GlobalVar::Instance().GetMeasureParam());
    });
    QTimer::singleShot(1000,this,[this]
    {
        if(!DialogValid::IsValid())
        {
            DialogValid d;
            if(d.exec()!=QDialog::Accepted)
            {
                qDebug()<<__FUNCTION__<<__LINE__<<"密码验证错误,程序退出!";
                qApp->quit();
            }
        }
    });
    startTimer(1000);
    ui->tabWidgetAnalysis->setCurrentIndex(0);
    ui->tabWidget_2->setCurrentIndex(0);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::Log(QString log)
{
    ui->txtLog->appendPlainText(log);
    if(ui->txtLog->document()->lineCount()>500)
    {
        ui->txtLog->document()->clear();
    }
}

void MainWindow::on_action_oepnConfigFile_triggered()
{
    // 创建QProcess对象
    static QProcess process;
    // 设置要启动的程序及其参数
    QString notepadPath = "C:\\Windows\\System32\\explorer.exe";
    QString filePath = ".\\Config";
    QStringList arguments;
    arguments << filePath;
    process.setProgram(notepadPath);
    process.setArguments(arguments);

    // 启动进程
    process.start();
    process.waitForFinished(300*1000);
}

void MainWindow::closeEvent(QCloseEvent *event)
{
    Q_UNUSED(event);
    qDebug()<<__LINE__;
    DeviceManager::Instance().WaitForEnd();
    qDebug()<<__LINE__;
    this->close();
    qApp->quit();
    qDebug()<<"程序关闭！";
}

void MainWindow::on_btnRun_clicked()
{
    WidgetUtils::Execute(sender(),[this]()
    {
        MeasureParam p=GetMeasureParam();
        GlobalVar::Instance().SetMeasureParam(p);
        ui->statusBar->showMessage("配置已保存!",3000);

        SpectroMeterControl &control=SpectroMeterControl::Instance();
        _measuredData.clear();
        _processedData.clear();
        _datas.clear();

        _dirName=QString("%1/%2").arg(p.SaveDir).arg(p.SampleMode);
        _stop = false;
         
        QThread *consumerThread = new QThread(this);
        ConsumerWorker *worker = new ConsumerWorker(_dirName, _firstSN, "", _totalPixelNumber, &_measuredData, &_measMutex, &_measCondition, &_stop);
        worker->moveToThread(consumerThread);


        connect(consumerThread, &QThread::started, worker, &ConsumerWorker::process);
        connect(worker, &ConsumerWorker::finished, consumerThread, &QThread::quit);
        connect(worker, &ConsumerWorker::finished, worker, &QObject::deleteLater);
        connect(consumerThread, &QThread::finished, consumerThread, &QObject::deleteLater);
        connect(worker, &ConsumerWorker::processingFinished, this, &MainWindow::onProcessingFinished);

        consumerThread->start();

        QThread *processThread = new QThread(this);
        ConsumerWorker *processWorker = new ConsumerWorker(_dirName, _firstSN, "_processed", _totalPixelNumber, &_processedData, &_procMutex, &_procCondition, &_stop);
        processWorker->moveToThread(processThread);


        connect(processThread, &QThread::started, processWorker, &ConsumerWorker::process);
        connect(processWorker, &ConsumerWorker::finished, processThread, &QThread::quit);
        connect(processWorker, &ConsumerWorker::finished, processWorker, &QObject::deleteLater);
        connect(processThread, &QThread::finished, processThread, &QObject::deleteLater);
        connect(processWorker, &ConsumerWorker::processingFinished, this, &MainWindow::onProcessingFinished);

        processThread->start();

        WaitUtils::Reset();
        control.ClearData();
        control.StartMeasure();
        QUIHelper::sleep(500);
        for(int i=0;i<p.SampleTimes;i++)
        {
            control.ClearData();

            if (ui->cmbTrigged->currentIndex() == 0)
            {
                control.SoftTrigger();
            }

            auto items=control.ReadData(p.IsRemoveBaseline);
            ui->statusBar->showMessage(QString("%1 接收到光谱").arg(QDateTime::currentDateTime().toString("hh:mm:ss.zzz")));

            for(int j=0;j<items.count();j++)
            {
                _plotWrap->Plot(items.at(j).resultData, j+1);
            }

            ui->lblMeasureProgress->setText(QString("%1/%2").arg(i+1).arg(ui->spinBoxSampleTimes->value()));
            //实时中断
            WaitUtils::WaitMsNoProgress(p.SampleIntervalMs);
            auto fullSpectrum = items.Combine();
            {
                QMutexLocker locker(&_measMutex);
                _measuredData.append(fullSpectrum);
                _measCondition.wakeOne();
            }

            if(p.IsRemoveBaseline||p.IsRemoveBlankLine)
            {
                _plotWrap->Plot(_processedData.last().resultData,0);
            }
            else
            {
                _plotWrap->Plot(QList<QPointF>(),0);
            }
        }
        _stop = true;
        _measCondition.wakeAll();
        _procCondition.wakeAll();
//        emit stopSignal();
        control.Stop();
        ui->statusBar->showMessage(QString("%1 over").arg(QDateTime::currentDateTime().toString("hh:mm:ss.zzz")));

        ui->horizontalSlider->setMaximum(_measuredData.count());
        Analysis(_measuredData,ui->cmbTestId->currentText());
    },true);
}

void MainWindow::onProcessingFinished(const QString &statusMessage)
{
    ui->statusBar->showMessage(statusMessage);
}

void MainWindow::Analysis(AvsMeasResultList data,QString type)
{
    if(type=="分辨率测试")
    {
    }
    else if(type=="效率测试")
    {
    }
}

MeasureParam MainWindow::GetMeasureParam()
{
    MeasureParam ret;
    ret.SampleTimes=ui->spinBoxSampleTimes->value();
    ret.SampleIntervalMs=ui->spinBoxSampleInterval->value();
    ret.SaveDir=ui->lineSaveRoot->text();
    ret.SampleMode=ui->cmbTestId->currentText();
    ret.IsRemoveBlankLine=ui->chbRemoveBlank->isChecked();
    ret.IsRemoveBaseline=ui->chbRemoveBase->isChecked();
    return ret;
}

MeasureParam MainWindow::SetMeasureParam(MeasureParam p)
{
    MeasureParam ret;
    ui->spinBoxSampleTimes->setValue(p.SampleTimes);
    ui->spinBoxSampleInterval->setValue(p.SampleIntervalMs);
    ui->lineSaveRoot->setText(p.SaveDir);
    ui->cmbTestId->setCurrentText(p.SampleMode);
    ui->chbRemoveBlank->setChecked(p.IsRemoveBlankLine);
    ui->chbRemoveBase->setChecked(p.IsRemoveBaseline);
    return ret;
}

void MainWindow::timerEvent(QTimerEvent *event)
{
//    DialogValid valid;
//    valid.exec();
}

void MainWindow::StartSave()
{
    FileUtils::CreateDir(_dirName);
    QString fileName=QString("%1_%2").arg(_firstSN).arg(QDateTime::currentDateTime().toString("yyyyMMddhhmmss"));
    QString filePath = QString("%1/%2_temp.csv").arg(_dirName).arg(fileName);

    QFile file(filePath);
    if(!file.open(QIODevice::WriteOnly | QIODevice::Text))
    {
        qDebug()<<"open file fail";
        return;
    }

    QTextStream out(&file);

    bool outputWavelength = true;
    while (true)
    {
        WaitUtils::WaitMs(1);
//        {
//            QMutexLocker locker(&_measMutex);
//            while (_measuredData.isEmpty() && !_stop)
//            {
//                _measCondition.wait(&_measMutex);
//            }
//        }
        if (_stop && _measuredData.isEmpty())
        {
            break;
        }

        if (!_measuredData.isEmpty())
        {
            AvsMeasResult data = _measuredData.takeFirst();
            int count = data.resultData.count();
            if (outputWavelength)
            {
                for (int i = 0; i < count; i++)
                {
                    out << data.resultData.at(i).x();
                    QString end=(i==(count-1))?"\n":",";
                    out << end;
                }
                outputWavelength = false;
            }
            for (int i = 0; i < count; i++)
            {
                out << data.resultData.at(i).y();
                QString end=(i==(count-1))?"\n":",";
                out << end;
            }
        }
    }
    file.close();
}


void MainWindow::SaveSpectrum(QString dirName)
{
    FileUtils::CreateDir(dirName);
    qDebug()<<__FUNCTION__<<__LINE__<<dirName;
    QString fileName=QString("%1_%2").arg(_measuredData.GetSerialIdList().first()).arg(QDateTime::currentDateTime().toString("yyyyMMddhhmmss"));
    QString filePath = QString("%1/%2.csv").arg(dirName).arg(fileName);
    _measuredData.Save(filePath);

    QString processedPath = QString("%1/%2_processed.csv").arg(dirName).arg(fileName);
    _processedData.Save(processedPath);

    ui->statusBar->showMessage(QString("%1 %2输出成功!").arg(filePath,processedPath),3000);
}

AvsMeasPara MainWindow::GetMeasParam()
{
    AvsMeasPara ret=_measPara;
    ret.integrationTime=ui->spinIntegraty->value();
    ret.integrationDelay=ui->spinIntegratyDelay->value();
    ret.NrAverages=ui->spinAverage->value();
    ret.triggerMode=ui->cmbTrigged->currentIndex();
    ret.triggerSource=ui->cmbTriggerSource->currentIndex();
    ret.isMasterChannel=ui->chbIsMaster->isChecked();
    return ret;
}

void MainWindow::SetMeasParam(AvsMeasPara para)
{
    _measPara=para;
    ui->spinIntegraty->setValue(_measPara.integrationTime);
    ui->spinIntegratyDelay->setValue(_measPara.integrationDelay);
    ui->spinAverage->setValue(para.NrAverages);
    ui->cmbTrigged->setCurrentIndex(para.triggerMode);
    ui->cmbTriggerSource->setCurrentIndex(para.triggerSource);
    ui->chbIsMaster->setChecked(para.isMasterChannel);
}

void MainWindow::on_btnStop_clicked()
{
    _stop = true;
    _measCondition.wakeAll();
    _procCondition.wakeAll();
    WaitUtils::Stop();
    DeviceManager::Instance().Stop();
    SpectroMeterControl::Instance().Stop();
}

void MainWindow::on_btnSearchDevice_clicked()
{
    WidgetUtils::Execute(sender(),[this]()
    {
        QList<SpectroInfoTag> infos;
        foreach (auto item, SpectroMeterControl::Instance().UpdateAllMeter()) {
            infos.append(item->GetSpectrumInfo());
        }
        if (infos.count() > 0)
        {
            _firstSN = infos.at(0).serilID;
            int total = 0;
            for (auto info : infos)
            {
                total += info.pixelNumber;
            }
            _totalPixelNumber = total;
        }
        ui->tableWidgetSpectroInfo->setRowCount(0);
        for(SpectroInfoTag iter:infos)
        {
            TableWidgetUtils::AddItem(ui->tableWidgetSpectroInfo,iter.GetMap(),iter.GetHeaders());
        }
        SetSpectroControl(infos.count()>0);
        QStringList labels;
        labels.append("处理后光谱");
        for(auto info:infos)
        {
            labels.append(info.serilID);
        }
        if(!infos.empty())
        {
            _plotWrap->SetGraph(labels);
        }
        _plotWrap->SetColors(QList<QColor>()<<QColor::fromRgb(250,20,20)<<QColor::fromRgb(20,250,20));
        ui->statusBar->showMessage(QString("搜索到%1个设备").arg(infos.count()),3000);
    });
}

void MainWindow::SetSpectroControl(bool enabled)
{
    ui->btnSetParam->setEnabled(enabled);
    ui->btnRun->setEnabled(enabled);
    ui->btnStop->setEnabled(enabled);
}

void MainWindow::on_btnDataImport_clicked()
{
    QString filePath = QFileDialog::getOpenFileName(this, "打开文件", "./LIBS_Data", "CSV 文件 (*.csv);;TXT 文件 (*.txt);;MYCSV 文件 (*.mycsv)");
    if(!filePath.isEmpty())
    {
        auto csvMat=FileUtils::ReadCsvFile(filePath);
        AvsMeasResultList avsList;
        avsList.Parase(csvMat);
        _measuredData=avsList;

        ui->horizontalSlider->setMaximum(_measuredData.count());
        qDebug()<<__FUNCTION__<<__LINE__<<_measuredData.count();
    }
}

void MainWindow::on_horizontalSlider_sliderMoved(int position)
{
    if(_measuredData.count()>position)
    {
        auto showList=_measuredData.GetItemList().mid(position,1);
        _plotWrap->Plot(showList.first(),1);
        _plotWrap->Plot(_processedData.last().resultData,0);
    }
}

void MainWindow::AnalysisResolution()
{
    QJsonObject obj;
    JsonUtils::LoadJsonObject("PeakList",obj);
    QList<SpecificPeak> peaks=SpecificPeak::ParaseFromJson(obj);
}

void MainWindow::on_btnSelectSaveRoot_clicked()
{
//    QString folderPath = QFileDialog::getExistingDirectory(this, "选择文件夹", ui->lineSaveRoot->text());
    QString folderPath = QFileDialog::getExistingDirectory(this, "选择文件夹",QDir::currentPath());
    if(!folderPath.isEmpty())
    {
        ui->lineSaveRoot->setText(folderPath);
    }
}

void MainWindow::on_cmbTestId_activated(int index)
{
    ui->tabWidgetAnalysis->setCurrentIndex(index);
    //效率测试
    if(index==2)
    {
//        AvsMeasResult standard=EffiencyAnalyzer::LoadStandard();
//        _plotWrap->Plot(standard.resultData.toList(),0);
    }
    else
    {
        _plotWrap->Plot(QList<QPointF>(),0);
    }
}

void MainWindow::on_actionHelp_triggered()
{
    // 创建一个QProcess实例
    static QProcess process;
    // 设置要执行的程序和文件路径作为参数
    process.start("notepad.exe", QStringList() << "./log.ini");
    // 等待进程完成
//    process.waitForFinished();
}

void MainWindow::on_tableWidgetSpectroInfo_clicked(const QModelIndex &index)
{
   _currentMeter=_spectroControl->GetSpectroMeter(index.row());
    AvsMeasPara para;
    _currentMeter->GetMeasParam(para);
    SetMeasParam(para);
}

void MainWindow::on_btnSetParam_clicked()
{
    if(_currentMeter==nullptr)
    {
        ui->statusBar->showMessage(QString("请选择一个光谱仪!"));
        return;
    }

    AvsMeasPara para=GetMeasParam();
    bool isOk=_currentMeter->SetMeasureParam(para);
    ui->statusBar->showMessage(QString("设置%1参数%2").arg(_currentMeter->GetSpectrumInfo().serilID).arg(isOk?"成功":"失败"));
}

void MainWindow::on_btnSetParams_clicked()
{
    for(int i=0;i<ui->tableWidgetSpectroInfo->rowCount();i++)
    {
         BaseSpectroMeter *meter=SpectroMeterControl::Instance().GetSpectroMeter(i);
         AvsMeasPara para=GetMeasParam();
         bool isOk=meter->SetMeasureParam(para);
         ui->statusBar->showMessage(QString("设置%1参数%2").arg(meter->GetSpectrumInfo().serilID).arg(isOk?"成功":"失败"));
         WaitUtils::WaitMsNoException(200);
    }
}


void MainWindow::on_actionDataTrans_triggered()
{
    QString filePath = QFileDialog::getOpenFileName(this, "打开文件", "./LIBS_Data", "Raw8 文件 (*.Raw8);");
    if(!filePath.isEmpty())
    {
        auto avsResult=AvsSpectroMeterUtils::Parse(filePath);
        AvsMeasResultList avsList;
        avsList.append(avsResult);

        auto matrix=avsList.GetStringMatrix();
        // 获取不带扩展名的全路径
        QFileInfo fileInfo(filePath);
        QString fullPathWithoutExtension = fileInfo.absolutePath() + "/" + fileInfo.baseName();
        QString newFilePath = QString("%1.csv").arg(fullPathWithoutExtension);
        FileUtils::ExportToCsv(matrix,newFilePath);
        ui->statusBar->showMessage(QString("%1输出成功!").arg(newFilePath),3000);

        _measuredData=avsList;
        ui->horizontalSlider->setMaximum(_measuredData.count());
    }
}

void MainWindow::on_radSoft_clicked()
{
    if(ui->radSoft->isChecked())
    {
        _spectroControl->SetTriggerMode(true);
    }
}

void MainWindow::on_radHard_clicked()
{
    QRadioButton* rad=dynamic_cast<QRadioButton*>(sender());
    if(rad->isChecked())
    {
        _spectroControl->SetTriggerMode(false);
    }
}

void MainWindow::on_btnSetBlank_clicked()
{
    _measuredData.Save("./Config/BlankLine.csv");
    ui->statusBar->showMessage(QString("设置背景光成功，%1!").arg("./Config/BlankLine.csv"),3000);
}

void MainWindow::on_btnSoftTrigger_clicked()
{
    if(_currentMeter==nullptr)
    {
        ui->statusBar->showMessage(QString("请选择一个光谱仪!"));
        return;
    }
    bool isOk=_currentMeter->SoftTrigger();
    ui->statusBar->showMessage(QString("执行软件触发%1").arg(isOk?"成功":"失败"));
}
